#include "exportobject.h"
#include "exporterutilitydesc.h"
#include "resource.h"
#include "maxtypes.h"
#include "stdmat.h"
#include <shaders.h>
#include "modstack.h"
#include <iskin.h>
#include "plugapi.h"
#include "matrix3.h"
#include "max.h"


////////////////////////////////////////////////////////////////////////////////////////////////
// CExportWeightMesh
////////////////////////////////////////////////////////////////////////////////////////////////
CExportWeightMesh::~CExportWeightMesh()
{
	delete[] Weights;
	//delete BonesMesh;
}

void CExportWeightMesh::FillData( INode *N )
{
	CExportMesh::FillData( N );

	ISkin *skinmod = ValidSkinModifier( N );
	//ASSERT(skinmod);

	int NumBones = skinmod->GetNumBones();

	ISkinContextData * skindata = skinmod->GetContextInterface( N );

	INode *RootBoneNode = FindRoot(skinmod->GetBone( 0 ));

	Object* Obj = N->EvalWorldState(0).obj;
	TriObject *triobj = (TriObject*)Obj->ConvertToType(0,Class_ID(TRIOBJ_CLASS_ID, 0));
	//ASSERT(triobj);
	Mesh& mesh = triobj->GetMesh();

	Weights = new ExportVertexWeight[NumVertices];

	for (int i = 0; i < NumVertices; i++ )
	{
		// Transform all the vertices with ObjectTM(), since we have to include this in vertices
		Matrix3 TrMat = N->GetObjectTM(0);
//		M.SetColumn( 0, M.GetColumn(0)*-1 ); // Mirror x axis
		Point3 P;
		P.x = Vertices[i].Vertex.x;
		P.y = Vertices[i].Vertex.y;
		P.z = Vertices[i].Vertex.z;
		P = P * TrMat;
		Vertices[i].Vertex.x = P.x;
		Vertices[i].Vertex.y = P.y;
		Vertices[i].Vertex.z =P.z;


		int assignedbones = skindata->GetNumAssignedBones( i );
		for ( int j = 0; j < assignedbones; j++ )
		{
			float weight = skindata->GetBoneWeight( i, j );
			if ( weight > MIN_INFLUENCE )
			{
				int fos = skindata->GetAssignedBone( i, j );
				//ASSERT(fos<MAX_BONES);
				ExportVertexWeight::BoneInfluence bonei;
				char *bname = skinmod->GetBoneName(fos);
				bonei.BoneName = bname==0?"Unnamed":string(bname);
				bonei.Weight = weight;
				Weights[i].Weights.push_back(bonei);
				/*Point3 P = skinmod->GetBone( fos )->GetObjectTM(0).GetTrans();
				Vertices[Faces[i].i[k]].Vertex.x -= P.x*weight;
				Vertices[Faces[i].i[k]].Vertex.y -= P.y*weight;
				Vertices[Faces[i].i[k]].Vertex.z -= P.z*weight;*/
				/*Matrix3 M = skinmod->GetBone( fos )->GetObjectTM(0);
				M.Invert();
				M*=weight;
				Point3 V;
				V.x = Vertices[Faces[i].i[k]].Vertex.x;
				V.y = Vertices[Faces[i].i[k]].Vertex.y;
				V.z = Vertices[Faces[i].i[k]].Vertex.z;
				V = V*M;
				Vertices[Faces[i].i[k]].Vertex.x = V.x;
				Vertices[Faces[i].i[k]].Vertex.y = V.y;
				Vertices[Faces[i].i[k]].Vertex.z = V.z;*/
			}
		}
	}

#if 0
		BonesMesh = new CExportMesh();
		BonesMesh->FillData( FindRoot(skinmod->GetBone( 0 )) );

		// Correct bone indices
		vector<string> L;
		BonesMesh->CreateHierarchyList( L );

		//	bool *bVertexDone = new bool[NumVertices];
		//	ZeroMemory( bVertexDone, sizeof(bool)*NumVertices );

		// correct bone indices
		for ( i = 0; i < NumVertices; i++ )
		{
			for ( int j = 0; j < 4; j++ )
			{
				string BoneName = skinmod->GetBoneName( Weights[i].BoneIndex[j] );
				int k = 0;
				bool bOk = false;
				for (vector<string>::const_iterator it = L.begin(); it != L.end(); ++it)
				{
					if ( (*it)==BoneName )
					{
						//ASSERT( j >= 0 && j < NumBones );
						Weights[i].BoneIndex[j] = k;
						bOk = true;
						break;
					}
					k++;
				}
				//ASSERT(bOk);
			}
		}
#endif
}
void CExportWeightMesh::BeginWrite( ostream &stream )
{   
	CExportMesh::BeginWrite(stream);
	stream << "<SkinWeights>" << endl;
	for (int i = 0; i < NumVertices; i++)
	{
		if (Weights[i].Weights.size())
		{
			for (int j = 0; j < Weights[i].Weights.size(); j++)
			{
				stream << "\t<SkinWeight VertexID=\"" << i << "\" Weight=\"" << Weights[i].Weights[j].Weight << "\" Bone=\"" << Weights[i].Weights[j].BoneName << "\" />" << endl;
			}
		}
	}
    stream << "</SkinWeights>" << endl;

}

void CExportWeightMesh::EndWrite( ostream &stream )
{
	CExportMesh::EndWrite(stream);
}

void CExportWeightMesh::CorrectBoneIndices()
{

}



